1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> #include <assert.h> #include <stdio.h> #include <time.h> #include <errno.h> #include <fcntl.h> #include <sys/ioctl.h> #include <unistd.h> #include <string.h>
#define BUFFER_SIZE 1023
int setnonblocking( int fd ) { int old_option = fcntl( fd, F_GETFL ); int new_option = old_option | O_NONBLOCK; fcntl( fd, F_SETFL, new_option ); return old_option; }
int unblock_connect( const char* ip, int port, int time ) { int ret = 0; struct sockaddr_in address; bzero( &address, sizeof( address ) ); address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port );
int sockfd = socket( PF_INET, SOCK_STREAM, 0 ); int fdopt = setnonblocking( sockfd ); ret = connect( sockfd, ( struct sockaddr* )&address, sizeof( address ) ); if ( ret == 0 ) { printf( "connect with server immediately\n" ); fcntl( sockfd, F_SETFL, fdopt ); return sockfd; } else if ( errno != EINPROGRESS ) { printf( "unblock connect not support\n" ); return -1; }
fd_set readfds; fd_set writefds; struct timeval timeout;
FD_ZERO( &readfds ); FD_SET( sockfd, &writefds );
timeout.tv_sec = time; timeout.tv_usec = 0;
ret = select( sockfd + 1, NULL, &writefds, NULL, &timeout ); if ( ret <= 0 ) { printf( "connection time out\n" ); close( sockfd ); return -1; }
if ( ! FD_ISSET( sockfd, &writefds ) ) { printf( "no events on sockfd found\n" ); close( sockfd ); return -1; }
int error = 0; socklen_t length = sizeof( error ); if( getsockopt( sockfd, SOL_SOCKET, SO_ERROR, &error, &length ) < 0 ) { printf( "get socket option failed\n" ); close( sockfd ); return -1; }
if( error != 0 ) { printf( "connection failed after select with the error: %d \n", error ); close( sockfd ); return -1; } printf( "connection ready after select with the socket: %d \n", sockfd ); fcntl( sockfd, F_SETFL, fdopt ); return sockfd; }
int main( int argc, char* argv[] ) { if( argc <= 2 ) { printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); return 1; } const char* ip = argv[1]; int port = atoi( argv[2] );
int sockfd = unblock_connect( ip, port, 10 ); if ( sockfd < 0 ) { return 1; } shutdown( sockfd, SHUT_WR ); sleep( 200 ); printf( "send data out\n" ); send( sockfd, "abc", 3, 0 ); return 0; }
|